using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using NDY_1.ContentDialogs;
using NDY_1.Model;
using OfficeOpenXml;

namespace NDY_1;
public partial class MainWindowViewModel:ViewModelBase
{
    private List<byte> _wholeBuff =new List<byte>(128);
    private readonly SerialPort _serialPort=new SerialPort();
    [ObservableProperty] private int _selectedIndex;
    [ObservableProperty] private string _portName;
    [ObservableProperty] private IEnumerable<String>? _portNames;
    [ObservableProperty] private float _ndValue=0.0f;
    [ObservableProperty] private float _wdValue = 0.0f;
    [ObservableProperty] private bool _isOpen=false;  
    [ObservableProperty] private ObservableCollection<Record> _records=new();
    [ObservableProperty] private string? _oilNumber = "неименованный файл";
    [ObservableProperty] private string? _verString = "";
    private const int StorageSize=77;

    //private readonly IMessenger _messenger;
    // private string _selectedItem;
    // public string SelectedItem
    // {
    //     get => _selectedItem;
    //     set
    //     {
    //         if (_selectedItem != value)
    //         {
    //             _selectedItem = value;
    //             OnPropertyChanged(nameof(SelectedItem));
    //             switch (SelectedIndex)
    //             {
    //                 case 0:Localizer.Localizer.Instance.LoadLanguage("chinese");
    //                     break;
    //                 case 1:Localizer.Localizer.Instance.LoadLanguage("russia");
    //                     break;
    //                 case 2:Localizer.Localizer.Instance.LoadLanguage("english");
    //                     break;
    //             }
    //         }
    //     }
    // }

    [RelayCommand]
    private void ShowWaves()
    {
    }

    [RelayCommand]
    private void CloseWindow()
    {
        if(_serialPort.IsOpen) _serialPort.Close();
    }

    [RelayCommand]
    private void ShowProgress()
    {
        
    }

    [RelayCommand]
    private void CloseProgressWindow()
    {
        
    }

    [RelayCommand]
    private void OpenSerialPort()
    {
        if (_serialPort.IsOpen) return;
        _serialPort.PortName = PortName;
        _serialPort.BaudRate = 115200;
        _serialPort.DataBits = 8;
        _serialPort.Parity = Parity.None;
        _serialPort.StopBits = StopBits.One;
        if(_serialPort.IsOpen) _serialPort.Close();
        _serialPort.Open();
        SendCommand(0x24); // 使能存储数据上传
        _serialPort.DataReceived+= SerialPortOnDataReceived;
    }
    
    [RelayCommand]
    private  void OpenOrClose()
    {
        switch (IsOpen)
        {
            case false:
                _serialPort.Close();
                break;
            case true:
                OpenSerialPort();
                break;
        }
    }

    private void SerialPortOnDataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        byte[] readBuffer = null;
        var lenth = _serialPort.BytesToRead;
        var buff = new byte[lenth];
         _serialPort.Read(buff,0,lenth);
        _wholeBuff.AddRange(buff);
        //读取数据上传帧
        while (_wholeBuff.Count>=28) 
        {
            if (_wholeBuff[0] == 0xFA && _wholeBuff[1] == 0x78) //帧头判断 FA 78
            {
                var len = 30;
                if (_wholeBuff.Count < len)break;   //数据未接收完整跳出循环
                readBuffer = new byte[30];
                _wholeBuff.CopyTo(0,readBuffer,0,30);
                _wholeBuff.RemoveRange(0, 30);
                DataProcess(readBuffer);//处理完整数据
            }
            else if (_wholeBuff[0] == 0xAA && _wholeBuff[1] == 0x66 && _wholeBuff[2] == 0x02 && _wholeBuff[3] == 0x26)
            {
                var len = 47*StorageSize;
                if (_wholeBuff.Count < len)break;   //数据未接收完整跳出循环
                readBuffer = new byte[len];
                _wholeBuff.CopyTo(0,readBuffer,0,len);
                _wholeBuff.RemoveRange(0, len);
                Task.Factory.StartNew(() =>
                {
                    UpdateStorageData(readBuffer);
                });//处理完整数据
            }
            else
            {
                _wholeBuff.RemoveAt(0);
            }
        }
    }

    private void UpdateStorageData(byte[] readBuffer)
    {
        byte[] buf = new byte[47*StorageSize];
        buf = readBuffer;
        var storage = new byte[47];
        var storageList = new ObservableCollection<Record>();

        for (int i = 0; i < StorageSize; i++)
        {
            Array.Copy(buf, i * 47, storage, 0, 47);
            var strBuilder = new StringBuilder();
            for (int j = 19; j < 34; j++)
            {
                var str=(char)storage[j];
                if (storage[j] != 0x00 && storage[j] != 0xFF) strBuilder.Append(str);
            }
            var record = new Record()
            {
                Index = (i + 1).ToString(),
                Time = (storage[5]>99)?String.Empty:(
                        (storage[5]+2000).ToString()+"-"+
                        storage[7].ToString()+"-"
                        +storage[9].ToString()+" "+
                        storage[12].ToString()+":"+    
                        storage[15].ToString()+":"+
                        storage[18].ToString()
                    ),
                Number = strBuilder.ToString(),
                NdValue = ((float)BitConverter.ToUInt16(new byte[]{storage[38],storage[37]})/10).ToString("F1"),
                WdValue = ((float)BitConverter.ToUInt16(new byte[]{storage[36],storage[35]})/10).ToString("F1"),
                ZsValue = BitConverter.ToUInt16(new byte[]{storage[42],storage[41]}).ToString("F0"),
                Nd100Value = ((float)BitConverter.ToUInt16(new byte[]{storage[44],storage[43]})/10).ToString("F1")
            };
            storageList.Add(record);
        }
        
        Dispatcher.UIThread.InvokeAsync(() =>
        {
            Records=storageList;
        });
    }

    private void DataProcess(byte[] data)
    {
        if (data[12] == 2)
        {
            var nd = new byte[2];
            nd[0] = data[20];
            nd[1] = data[19];
            NdValue = (float)BitConverter.ToUInt16(nd, 0)/10;

            
        }
        else if(data[12]==0)
        {
            var wd = new byte[2];
            wd[0] = data[14];
            wd[1] = data[13];
            WdValue = (float)BitConverter.ToUInt16(wd, 0)/10;
        }
        else if(data[12]==1)
        {
            var ver = new StringBuilder();
            ver.Append(data[21].ToString("D2"));
            ver.Append('.');
            ver.Append(data[22].ToString("D2"));
            VerString = ver.ToString();
        }
    }

    public MainWindowViewModel()
    {
        PortNames = SerialPort.GetPortNames();
        // byte buf1 = 0x01;
        // byte buf2 = 0x0A;
        // VerString=buf1.ToString("D2")+"."+buf2.ToString("D2");
        //PortNames = [];
        if (!PortNames.Any())
        {
            PortNames = [];
            //MessageBox.Show("没有可用端口，请检查设备是否连接");
        }
        else
        {
            PortName = PortNames.First();
        }
        
    }

    // [RelayCommand]
    // private void GenerateRecord()
    // {
    //     for (int i = 0; i < 20; i++)
    //     {
    //         var record = new Record()
    //         {
    //             Index = (Records.Count + 1).ToString(),
    //             Time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
    //             Number = "123456789",
    //             NdValue = NdValue,
    //             WdValue = WdValue,
    //             ZsValue = 0,
    //             Nd100Value = 0
    //         };
    //         Records.Add(record);
    //     }
    // }
    [RelayCommand]
    private void RefreshPortName() {
        PortNames = SerialPort.GetPortNames();
        PortName = PortNames.First();
    }

    [RelayCommand]
    private async Task SaveRecords(object obj)
    {
        var mainWindow = obj as MainWindow;
        var saveFileDialog = new SaveFileDialog();
        saveFileDialog.Directory = ".";
        saveFileDialog.InitialFileName = "Nd-"+DateTime.Now.ToString(("yyyyMMddHHmmss"))+".xlsx";
        saveFileDialog.Filters.Add(new FileDialogFilter { Name = "Excel Files", Extensions = { "xlsx"}});
        var result =await saveFileDialog.ShowAsync(mainWindow);
        if (result != null)
        {
            ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
            using var package = new ExcelPackage();
            var sheet = package.Workbook.Worksheets.Add("NdSheet");
            sheet.Cells["A1"].Value = "Index";
            sheet.Cells["B1"].Value = "DateTime";
            sheet.Cells["C1"].Value = "Number";
            sheet.Cells["D1"].Value = "Temperature";
            sheet.Cells["E1"].Value = "Viscosity";
            sheet.Cells["F1"].Value = "Parameter";
            sheet.Cells["G1"].Value = "Viscosity@100℃";
            for (int i = 0; i < Records.Count; i++)
            {
                sheet.Cells[i + 2, 1].Value = Records[i].Index;
                sheet.Cells[i + 2, 2].Value = Records[i].Time;
                sheet.Cells[i + 2, 3].Value = Records[i].Number;
                sheet.Cells[i + 2, 4].Value = Records[i].WdValue;
                sheet.Cells[i + 2, 5].Value = Records[i].NdValue;
                sheet.Cells[i + 2, 6].Value = Records[i].ZsValue;
                sheet.Cells[i + 2, 7].Value = Records[i].Nd100Value;
            }
            await package.SaveAsAsync(new System.IO.FileInfo(result));
        }

        
    }

    //刷新存储数据
    [RelayCommand]
    private void EnableUpdateStorage()
    {
        Records.Clear();
        SendCommand(0x24);
    }
    //启动/停止检测
    [RelayCommand]
    private void StartCheck()
    {
        SendCommand(0x03);
    }
    //发送40℃温度设置
    [RelayCommand]
    private void Set40Temp()
    {
        SendTempFrame(0x00);
    }
    //发送50℃温度设置
    [RelayCommand]
    private void Set50Temp()
    {
        SendTempFrame(0x01);
    }
    //发送100℃温度设置
    [RelayCommand]
    private void Set100Temp()
    {
        SendTempFrame(0x02);
    }
    //保存当前记录
    [RelayCommand]
    private void SaveCurrentLog()
    {
        SendSaveCurrentLogCommand(OilNumber);
        Thread.Sleep(100);
        Records.Clear();
        SendCommand(0x24);
    }
    //发送FA 78 1A code
    private void SendTempFrame(byte code=0x00 )
    {
        var frame = new List<byte> { 0xFA, 0x78, 0x1A,code};
        _serialPort.Write(frame.ToArray(),0,frame.Count);
    }
    //发送FA 78 00 code
    private void SendCommand(byte code=0x00)
    {
        var frame = new List<byte>
        {
            0xFA, 0x78, 0x00,
            code
        };
        _serialPort.Write(frame.ToArray(),0,frame.Count);
    }

    private void SendSaveCurrentLogCommand(string str) {
        var cs =str.ToArray();
        var frame = new List<byte> { 
            0xFA,0x78,0x00,0x10
        };
        foreach (var c in cs) {
            frame.Add(Convert.ToByte(c));
        }
        _serialPort.Write(frame.ToArray(), 0, frame.Count);
    }
}